import Observer from './observer';

class VNode {
  /**
   * 实例化
   * @param {*} param0 虚拟节点配置
   */
  constructor({
    type = 'div',
    content = '',
    attrs = {},
    styles = {},
    events = {},
    children = [],
    watch = {}
  }) {
    this.type = type;
    this.content = content;
    this.attrs = attrs;
    this.styles = styles;
    this.events = events;
    this.children = children.filter(c => c instanceof VNode);
    this.watch = watch;
    Object.keys(watch).forEach(key => {
      Observer.listener(watch[key], this);
    })
  }

  /**
   * 触发渲染
   * @param {*} config 回调或参数配置
   */
  render(config = {}) {
    const node = document.createElement(this.type);
    node.innerHTML = this.content;
    Object.keys(this.attrs).forEach(key => {
      node.setAttribute(key, this.attrs[key]);
    });
    Object.keys(this.styles).forEach(key => {
      node.style[key] = this.styles[key];
    });
    Object.keys(this.events).forEach(key => {
      node.addEventListener(key, e => {
        e.$config = config; // 注入配置
        try {
          this.events[key].call(this, e); // 更改this指向
        } catch (error) {
          console.error(error);
        }
      });
    });
    this.children.forEach(n => {
      node.appendChild(n.render(config));
    });
    return node;
  }

  /**
   * 挂载到原型
   * @param {*} key 
   * @param {*} value 
   */
  static use(key = '_', value = {}) {
    if (key && value) {
      VNode.prototype[`$${key.replace(/^\$/, '')}`] = value;
    }
  }
}

module.exports = VNode;